package com.yonyou.cyxdms.sysAuth.service.service.Login;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yonyou.cyx.framework.compent.redis.RedisClient;
import com.yonyou.cyx.framework.util.bean.ApplicationContextHelper;
import com.yonyou.cyx.function.exception.ServiceBizException;
import com.yonyou.cyx.function.utils.common.StringUtils;
import com.yonyou.cyxdms.framework.bean.dto.user_info.LoginInfoDto;
import com.yonyou.cyxdms.sysAuth.service.constants.Constanst;
import com.yonyou.cyxdms.sysAuth.service.entity.EmpPo;
import com.yonyou.cyxdms.sysAuth.service.mapper.EmpMapper;
import com.yonyou.cyxdms.sysAuth.service.service.EmpService;
import com.yonyou.cyxdms.sysAuth.service.utill.AesUtil;
import com.yonyou.cyxdms.sysAuth.service.utill.DateUtils;
import com.yonyou.cyxdms.sysAuth.service.utill.HttpClientUtils;
import com.yonyou.cyxdms.sysAuth.service.vo.weChat.AccessToken;
import com.yonyou.cyxdms.sysAuth.service.vo.weChat.AccountBindingVO;
import com.yonyou.cyxdms.sysAuth.service.vo.weChat.HttpParame;
import com.yonyou.cyxdms.sysAuth.service.vo.weChat.WechatInfo;
import com.yonyou.cyxdms.sysmanage.client.domains.dto.SmsPushDTO;
import com.yonyou.cyxdms.sysmanage.client.service.login.PushServices;
import org.apache.commons.lang3.RandomUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * <p>Title: WechatScanLoginServiceImpl</p>
 * <p>Description: 业务接口实现 </p>
 *
 * @author 李贺
 */
@Service
public class WechatScanLoginServiceImpl implements WechatScanLoginService {

    private final Logger logger = LoggerFactory.getLogger(WechatScanLoginServiceImpl.class);

    @Value("${pcwc.appid}")
    private String appid;
    @Value("${pcwc.redirectUri}")
    private String redirectUri;
    @Value("${pcwc.secret}")
    private String secret;
    @Autowired
    private PushServices pushService;

    @Value("${sms.templateId-1}")
    private String templateId1;
    @Autowired
    private RedisClient redisClient;
    @Autowired
    private EmpMapper empMapper;
    @Autowired
    private EmpService empService;

    /**
     * <p>Title: wechatLoginUrl</p>
     * <p>Description: 网页授权回调地址处理</p>
     *
     * @return Map
     */
    @Override
    public Map<String, String> wechatLoginUrl(String redirectUri) {
        String content = Constanst.WX_MD5 + DateUtils.getYYYYMMdd();
        byte[] encrypt = AesUtil.encrypt(content, AesUtil.PW_SECRET_KEY, 16);
        String parseByte2HexStr = AesUtil.parseByte2HexStr(Objects.requireNonNull(encrypt));
        Map<String, String> map = new HashMap<>();
        String url = HttpParame.AUTHORIZATION_URL;


        logger.error("获取服务器配置 appid:{}", appid);
        String uri = redirectUri;
        logger.error("获取服务器配置 uri:{}", uri);
        url = url.replaceAll("APPID", appid);
        try {
            url = url.replaceAll("REDIRECT_URI", URLEncoder.encode(uri, "UTF-8"));
        } catch (UnsupportedEncodingException e) {
            logger.error("网页授权回调地址处理失败",e);
        }
        url = url.replaceAll("SCOPE", "snsapi_login");
        //加密state进行验证 回调地址当天有效 防止恶意攻击
        url = url.replace("STATE", parseByte2HexStr);
        map.put("url", url);
        return map;
    }

    /**
     * <p>Title: getAccessToken</p>
     * <p>Description: 用户授权后获取用户唯一标识 </p>
     */
    @Override
    public AccessToken getAccessToken(String code) {
        String accessTokenUrl = HttpParame.ACCESS_TOKEN_URL;

        logger.error("获取服务器配置 appid: " + appid);

        logger.error("获取服务器配置 secret: " + secret);
        accessTokenUrl = accessTokenUrl.replaceAll("APPID", appid);
        accessTokenUrl = accessTokenUrl.replaceAll("SECRET", secret);
        accessTokenUrl = accessTokenUrl.replaceAll("CODE", code);
        logger.error("accessTokenUrl:" + accessTokenUrl);
        String responseContent = HttpClientUtils.getInstance().sendHttpGet(accessTokenUrl);
        if (responseContent == null || "".equals(responseContent)) {
            logger.error("901：微信登录授权失败！");
            throw new ServiceBizException("微信登录授权失败！");
        }
        logger.error("responseContent:" + responseContent);
        JSONObject parseObject = JSONObject.parseObject(responseContent);
        return JSONObject.toJavaObject(parseObject, AccessToken.class);
    }

    @Override
    public WechatInfo getWechatInfo(String accessToken, String openId) {
        String accessInfoUrl = HttpParame.ACCESS_INFO_URL;
        accessInfoUrl = accessInfoUrl.replaceAll("ACCESS_TOKEN", accessToken);
        accessInfoUrl = accessInfoUrl.replaceAll("OPENID", openId);
        String responseContent = HttpClientUtils.getInstance().sendHttpGet(accessInfoUrl);
        if (responseContent == null || "".equals(responseContent)) {
            logger.error("901：获取微信个人信息失败！");
            throw new ServiceBizException("获取微信个人信息失败！");
        }

        JSONObject parseObject = JSONObject.parseObject(responseContent);
        return JSONObject.toJavaObject(parseObject, WechatInfo.class);
    }

    @Override
    public void sendSms(String phone, String appId) {
        LoginInfoDto loginInfoDto = ApplicationContextHelper.getBeanByType(LoginInfoDto.class);
        loginInfoDto.setAppId(appId);
        SmsPushDTO smsPushDTO = new SmsPushDTO();
        smsPushDTO.setMobiles(phone);
        smsPushDTO.setTemplateId(templateId1);
        StringBuilder code = new StringBuilder();
        for (int i = 0; i < 6; i++) {
            code.append(RandomUtils.nextInt(0, 10));
        }
        Map<String, String> params = new HashMap<>();
        params.put("1", code.toString());
        params.put("2", "5");
        smsPushDTO.setParamMap(params);
        String f4Result = pushService.sendSms(smsPushDTO);
        logger.info("短信发送返回结果f4Result：{}", f4Result);
        redisClient.set("cyxdms:login:" + appId + ":" + phone, code.toString(), 5 * 60 * 1000L);
    }

    @Override
    @Transactional
    public void accountBinding(AccountBindingVO accountBindingVO) {

        String phone = accountBindingVO.getPhone();
        String code = (String) redisClient.get("cyxdms:login:" + accountBindingVO.getAppId() + ":" + phone);
        if (accountBindingVO.getVerificationCode().equals(code)) {
            QueryWrapper<EmpPo> empPoQueryWrapper = new QueryWrapper<>();
            empPoQueryWrapper.eq("MOBILE_PHONE", phone).eq("app_id", accountBindingVO.getAppId());
            EmpPo empPo = empMapper.selectOne(empPoQueryWrapper);
            empPo.setOpenId(accountBindingVO.getOpenid());
            empPo.setWechat(accountBindingVO.getNickname());
            empPo.setHeadPortrait(accountBindingVO.getHeadimgurl());
            empMapper.updateById(empPo);
            redisClient.del("cyxdms:login:" + accountBindingVO.getAppId() + ":" + phone);
        } else {
            throw new ServiceBizException("验证码输入错误");
        }
    }

    @Override
    public Map<String, Object> checkOpenId(String strOpenid, String appId) {
        Map<String, Object> map = new HashMap<>();
        EmpPo empPo = new EmpPo();

        if (StringUtils.isNullOrEmpty(appId)) {
            appId = "cyx";
        }
        try {
            empPo = empService.getEmpInfoByOpenId(strOpenid, appId);
            map.put("openid", strOpenid);
            map.put("flag", "true");
            map.put("appId", empPo.getAppId());
            map.put("loginType", 3);
        } catch (ServiceBizException e) {
            map.put("openid", strOpenid);
            map.put("flag", "false");
        }

        return map;
    }
}
